/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.formserver.vmmanager.generatacmpcode;


import com.inspur.edp.formserver.viewmodel.GspViewModel;
import com.inspur.edp.formserver.viewmodel.action.IViewModelParameter;
import com.inspur.edp.formserver.viewmodel.action.MappedCdpAction;
import com.inspur.edp.formserver.viewmodel.action.viewmodelbase.ViewModelParameter;
import com.inspur.edp.formserver.viewmodel.action.viewmodelbase.ViewModelVoidReturnValue;
import com.inspur.edp.formserver.viewmodel.common.VMCollectionParameterType;
import com.inspur.edp.formserver.viewmodel.common.VMParameterType;
import com.inspur.edp.formserver.viewmodel.util.ViewModelUtils;
import com.inspur.edp.formserver.vmmanager.exception.VmManagerException;
import io.iec.edp.caf.commons.exception.ExceptionLevel;

import java.util.Map;

public abstract class JavaBaseActionGenerator extends JavaBaseCompCodeGenerator
{

		///#region 字段和属性
	private MappedCdpAction vmAction;
	private java.util.ArrayList<String> usingList;
	private java.util.LinkedHashMap<String, ParameterInfo> parameters;
	private java.util.ArrayList<Class> allGenericParamType;
	protected String ReturnTypeName = "VoidActionResult";
	protected String errorCode = "VmBaseActionGenerator";

		///#endregion
		///#region 构造与初始化
	public JavaBaseActionGenerator(GspViewModel vm, MappedCdpAction vmAction, String nameSpace, String path)
	{
		super(vm, vmAction, nameSpace, path);
		this.vmAction = vmAction;
		if (this.vmAction == null)
		{
			throw new RuntimeException("选择了错误的代码模板生成器");
		}
		this.usingList = new java.util.ArrayList<String>();
		this.allGenericParamType = new java.util.ArrayList<Class>();


			///#region ReturnValue
		if (this.vmAction.getReturnValue() != null && !(this.vmAction.getReturnValue() instanceof ViewModelVoidReturnValue))
		{
			getParameterUsing(this.vmAction.getReturnValue());
			ReturnTypeName = GetParameterTypeName(this.vmAction.getReturnValue());
		}

			///#endregion


			///#region Parameters
		if (this.vmAction.getParameterCollection() == null || this.vmAction.getParameterCollection().getCount() < 1)
		{
			return;
		}
		parameters = new java.util.LinkedHashMap<String, ParameterInfo>();

		for (Object actionParameter : this.vmAction.getParameterCollection())
		{
			getParameterUsing((IViewModelParameter) actionParameter);
			if (parameters.containsKey(((IViewModelParameter) actionParameter).getParamCode()))
			{
				throw new RuntimeException("存在重复的参数【" + ((IViewModelParameter) actionParameter).getParamCode() + "】");
			}
			parameters.put(((IViewModelParameter) actionParameter).getParamCode(), buildParameterInfo(
					(IViewModelParameter) actionParameter));


		}

			///#endregion
	}
	private void getParameterUsing(IViewModelParameter param)
	{
		if (param.getCollectionParameterType() == VMCollectionParameterType.List)
		{
			addUsing(JavaCompCodeNames.ArrayListNameSpace);
		}
		if (param.getParameterType() == VMParameterType.DateTime)
		{
			addUsing(JavaCompCodeNames.DateNameSpace);
		}
		if (param.getParameterType() == VMParameterType.Decimal)
		{
			addUsing(JavaCompCodeNames.BigDecimalNameSpace);
		}
		if (param.getParameterType() == VMParameterType.Custom)
		{
			addUsing(param.getClassName());
		}
	}
	private String GetParameterTypeName(IViewModelParameter param)
	{
		switch (param.getCollectionParameterType())
		{
			case None:
				return GetNoneCollectionParaTypeName(param);
			case List:
				return GetListParaTypeName(param);
			case Array:
				return GetArrayParaTypeName(param);
			default:
				throw new VmManagerException("",errorCode, "无效的Vo操作参数集合类型{param.CollectionParameterType.ToString()}",null,
						ExceptionLevel.Error,false);
		}
	}

	private String GetArrayParaTypeName(IViewModelParameter param)
	{
		switch (param.getParameterType())
		{
			case String:
				return "String[]";
			case Boolean:
				return "Boolean[]";
			case DateTime:
				return "Date[]";
			case Decimal:
				return "BigDecimal[]";
			case Double:
				return "Double[]";
			case Int32:
				return "Integer[]";
			case Object:
				return "Object[]";
			default:
				handleJavaInfo(param);
				if (ViewModelUtils.checkNull(param.getClassName()))
				{
					throw new RuntimeException("当前参数【" + param.getParamName() + "】的JavaClassName属性为空，请完善。");
				}
				int index = param.getClassName().lastIndexOf(".");
				return param.getClassName().substring(index + 1, param.getClassName().length())+"[]";
//				if (!IsGeneric(param))
//				{
//					return param.getJavaClassName().substring(index + 1, index + 1 + param.getJavaClassName().length() - index - 1) + "[]";
//				}
//				else
//				{
//					String result = GetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return result + "[]";
//				}

		}

	}

	private String GetListParaTypeName(IViewModelParameter param)
	{
		switch (param.getParameterType())
		{
			case String:
				return "ArrayList<String>";
			case Boolean:
				return "ArrayList<Boolean>";
			case DateTime:
				return "ArrayList<Date>";
			case Decimal:
				return "ArrayList<BigDecimal>";
			case Double:
				return "ArrayList<Double>";
			case Int32:
				return "ArrayList<Integer>";
			case Object:
				return "ArrayList<Object>";
			default:
				handleJavaInfo(param);
				if (ViewModelUtils.checkNull(param.getClassName()))
				{
					throw new RuntimeException("当前参数【" + param.getParamName() + "】的JavaClassName属性为空，请完善。");
				}
				int index = param.getClassName().lastIndexOf(".");
				return "ArrayList<"+param.getClassName().substring(index + 1, param.getClassName().length())+">";
//				if (!IsGeneric(param))
//				{
//					return "ArrayList<" + param.getJavaClassName().substring(index + 1, index + 1 + param.getJavaClassName().length() - index - 1) + ">";
//				}
//				else
//				{
//					String result = GetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return "ArrayList<" + result + ">";
//				}

		}
	}

	private String GetNoneCollectionParaTypeName(IViewModelParameter param)
	{
		switch (param.getParameterType())
		{
			case String:
				return "String";
			case Boolean:
				return "Boolean";
			case DateTime:
				return "Date";
			case Decimal:
				return "BigDecimal";
			case Double:
				return "Double";
			case Int32:
				return "Integer";
			case Object:
				return "Object";
			default:
				handleJavaInfo(param);
				if (ViewModelUtils.checkNull(param.getClassName()))
				{
					throw new RuntimeException("当前参数【" + param.getParamName() + "】的JavaClassName属性为空，请完善。");
				}
				int index = param.getClassName().lastIndexOf(".");
				return param.getClassName().substring(index + 1, param.getClassName().length());
//				if (!IsGeneric(param))
//				{
//					return param.getJavaClassName().substring(index + 1, index + 1 + param.getJavaClassName().length() - index - 1);
//				}
//				else
//				{
//					String result = GetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return result;
//				}

		}
	}

	private String getParameterMode(IViewModelParameter param)
	{
		switch (param.getMode())
		{
			case OUT:
				return "out";
			//TODO 待确认
			case INOUT:
				return "ref";
			default:
				return "";
		}

	}
	private ParameterInfo buildParameterInfo(IViewModelParameter param)
	{
		String typeName = GetParameterTypeName(param);
		String paramMode = getParameterMode(param);
		ParameterInfo tempVar = new ParameterInfo();
		tempVar.setParamName(param.getParamCode());
		tempVar.setParamType(typeName);
		tempVar.setParameterMode(paramMode);
		return tempVar;
	}

	@Override
	protected void generateExtendUsing(StringBuilder result)
	{
		result.append(getUsingStr(JavaCompCodeNames.FormServerSpiNameSpace));
		result.append(getUsingStr(JavaCompCodeNames.BefApiActionNameSpace));

		//参数列表
		if (usingList == null || usingList.size() < 1)
		{
			return;
		}
		for (String usingName : usingList)
		{
			result.append(getUsingStr(usingName));
		}
	}

	protected  boolean hasCustomConstructorParams()
	{
		if (parameters == null || parameters.size() < 1)
		{
			return false;
		}
		return true;
	}
	protected  void generateConstructorParams(StringBuilder result)
	{
		for (int i = 0; i < parameters.size(); i++)
		{

			String parameterKey = (String) parameters.keySet().toArray()[i];

			ParameterInfo parameterValue = parameters.get(parameterKey);

			if (!ViewModelUtils.checkNull(parameterValue.getParameterMode()))
			{
				result.append(parameterValue.getParameterMode()).append(" ");
			}
			result.append(parameterValue.getParamType()).append(" ").append(parameterKey);
			if (i < parameters.size() - 1)
			{
				result.append(",");
			}
			else
			{
				result.append("");
			}
		}
	}

	protected  void generateConstructorContent(StringBuilder result)
	{
		if (parameters == null || parameters.size() < 1)
		{
			return;
		}

		for (Map.Entry<String,ParameterInfo> parameter : parameters.entrySet())
		{
			result.append(getNewLine()).append(getIndentationStr()).append(getIndentationStr()).append("this.").append(parameter.getKey()).append(" = ").append(parameter.getKey()).append(";");

		}
	}

		///#endregion


		///#region Field
	@Override
	protected void generateField(StringBuilder result)
	{

		if (parameters == null || parameters.size() < 1)
		{
			return;
		}

		for (Map.Entry<String,ParameterInfo> parameter : parameters.entrySet())
		{
			result.append(getNewLine()).append(getIndentationStr()).append(JavaCompCodeNames.KeywordPrivate).append(" ").append(parameter.getValue().getParamType()).append(" ").append(parameter.getKey()).append(";");
		}
	}

		///#endregion
//TODO 后续确认
	private boolean IsGeneric(IViewModelParameter param)
	{
		return false;
//		try
//		{
//
//			var psn = Assembly.Load(param.getAssembly());
//			Class type = psn.GetType(param.getJavaClassName());
//			return type.IsGenericType;
//		}
//		catch (Exception e)
//		{
//			//如果libs目录下如果未加载到程序集，默认其不是泛型类型
//			return false;
//		}
	}
	//TODO 后续确认
	//把泛型参数类型涉及到的所有类型得到并存在List集合中
	private void getAllGenericParameterType(Class type)
	{
//		if (allGenericParamType.isEmpty())
//		{
//			allGenericParamType.add(type);
//		}
//		Class[] allType = type.getGenericArguments();
//
//		for (Class t : allType)
//		{
//			allGenericParamType.add(t);
//			if (t.IsGenericType)
//			{
//				getAllGenericParameterType(t);
//			}
//		}

	}

	private void addUsing(String usingName)
	{
		if (ViewModelUtils.checkNull(usingName))
		{
			throw new RuntimeException("命名空间不能为空");
		}
		if (!ViewModelUtils.checkNull(usingName) && !usingList.contains(usingName))
		{
			usingList.add(usingName);
		}
	}

	private String getClassName(Class type)
	{
		if (Integer.class == type)
		{
			return "Integer";
		}
		if (String.class == type)
		{
			return "String";
		}
		if (Boolean.class == type)
		{
			return "Boolean";
		}
		if (java.util.Date.class == type)
		{
			return "Date";
		}
		if (java.math.BigDecimal.class == type)
		{
			return "BigDecimal";
		}
		if (Double.class == type)
		{
			return "BigDecimal";
		}
		if (Object.class == type)
		{
			return "Object";
		}
		
		String fullClassName = type.toString().split("[`]", -1)[0];
		String[] content = fullClassName.split("[.]", -1);
		return content[content.length - 1];


	}
//TODO 后续确认
	private String getGenericExpress(Class type)
	{
//		if (!type.IsGenericType)
//		{
//			return getClassName(type);
//		}
//		else
//		{
//			Class[] array = type.GenericTypeArguments;
//			int count = array.length;
//			String info = "{0}";
//			for (int i = 1; i < count; i++)
//			{
//				info = info + "," + "{" + i + "}";
//			}
//			info = getClassName(type) + "<" + info + ">";
//			String[] arrayStr = new String[count];
//			for (int i = 0; i < count; i++)
//			{
//				arrayStr[i] = getGenericExpress(array[i]);
//			}
//			info = String.format(info, arrayStr);
//
//			return info;
//		}
		return "";
	}

	private void handleJavaInfo(IViewModelParameter para)
	{
		if (ViewModelUtils.checkNull(para.getClassName()) && !ViewModelUtils.checkNull(((ViewModelParameter)para).getDotnetClassName()))
		{
			//仅平台提供包，自动转Inspur.Gsp为com.inspur.edp
			if (((ViewModelParameter)para).getDotnetClassName().startsWith("Inspur.Gsp."))
			{
				para.setClassName(handleJavaClassName(((ViewModelParameter)para).getDotnetClassName()));
			}
		}
	}

	private String handleJavaClassName(String source)
	{
		if (ViewModelUtils.checkNull(source))
		{
			return source;
		}
		String result = "";
		String[] list = source.split("[.]", -1);
		for (int i = 0; i < list.length; i++)
		{
			String lowerCase = list[i].toLowerCase();
			if (i == 0 && lowerCase.equals("inspur"))
			{
				result = String.format("%1$s%2$s",result, "com.inspur");
				continue;
			}
			if (i == list.length - 1)
			{
				// 类名不需要转换为小写
				result = String.format("%1$s%2$s%3$s",result, ".", list[i]);
				continue;
			}
			result = String.format("%1$s%2$s%3$s",result, ".", lowerCase);
		}
		return result;
	}
}
